package com.example.service.impl;

import java.math.BigDecimal;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Service;

import com.example.dao.FactorOptionRepository;
import com.example.dao.FactorRepository;
import com.example.dao.InsuranceFormRepository;
import com.example.dao.InsuranceRepository;
import com.example.dao.PolicyFactorRepository;
import com.example.dao.ProductRepository;
import com.example.dao.SubInsuranceDetailRepository;
import com.example.dao.UserDao;
import com.example.entity.Factor;
import com.example.entity.FactorOption;
import com.example.entity.Insurance;
import com.example.entity.InsuranceForm;
import com.example.entity.PolicyFactor;
import com.example.entity.Product;
import com.example.entity.SubInsuranceDetail;
import com.example.service.FactorHandleService;
import com.example.service.ProductCenterService;

@Service
public class ProductCenterServiceImpl implements ProductCenterService, ApplicationContextAware {
	@Autowired
	private UserDao userDao;
	@Autowired
	private ProductRepository productDao;
	@Autowired
	private FactorRepository factorDao;
	@Autowired
	private FactorOptionRepository factorOptionDao;
	@Autowired
	ProductCenterService productCenterService;
	@Autowired
	InsuranceRepository insuranceDao;
	@Autowired
	InsuranceFormRepository insuranceFormDao;
	@Autowired
	SubInsuranceDetailRepository subInsuranceDetailDao;
	@Autowired
	PolicyFactorRepository policyFactorDao;
	@Autowired
	FactorHandleService factorHandleService;
	
	@Override
	public String[] createCalculator(HttpServletRequest request) {
		String strs[]=new String [2];
		String baseFee = request.getParameter("baseFee");
		Factor baseFeeFactor=factorDao.findById(Long.parseLong(baseFee));
		String baseFeeStr=packageFactor(baseFeeFactor);
		
		String formula=baseFeeStr;
		String formulaDesc=baseFeeFactor.getFactorName();
		String[] factorArray = request.getParameterValues("factorArray");
		for(String one:factorArray){
			Factor factor=factorDao.findById(Long.parseLong(one));
			formula=formula+"*"+packageFactor(factor);
			formulaDesc=formulaDesc+"X"+factor.getFactorName();
		}
		strs[0]=formula;
		strs[1]=formulaDesc;
		
		return strs;
	}
	public String packageFactor(Factor factor){
		if(factor.getFactorDataType().equals("1")){
			return "?"+factor.getFactorName()+"?";
		}else if(factor.getFactorDataType().equals("2")){
			return "?"+factor.getFactorName()+"?";
		}else if(factor.getFactorDataType().equals("3")){
			return "$"+factor.getFactorName()+"$";
		}else if(factor.getFactorDataType().equals("4")){
			return "?"+factor.getFactorName()+"?";
		}else{
			throw new RuntimeException();
		}
	}
	/**查找产品定义详情**/
	@Override
	public Product findProductDetail(Product product) {
		Long id=product.getId();
		product=productDao.findById(id);
		
		if(product==null){
			throw new RuntimeException("没有查到产品定义");
		}
		
		List<Insurance>insuranceList=insuranceDao.findByProductId(product.getId());
		
		
		for(Insurance one : insuranceList){
			this.injectFactor(one);
		}
		product.setInsuranceList(insuranceList);
		
		return product;
	}
	@Override
	public void injectFactor(Insurance one) {
		String formula = one.getFormula();
		String[]factorStrs=formula.split("\\*");
		Factor[] factors=new Factor[factorStrs.length];
		for(int i=0;i<factorStrs.length;i++){
			String str=factorStrs[i];
			Factor factor=new Factor();
			str=str.replace("?", "").replace("$", "");
			factor=factorDao.findByFactorName(str);
			if("2".equals(factor.getFactorDataType())){
				injectFactorOptions(factor);
			}else if("3".equals(factor.getFactorDataType())){
				//TODO
				//reflect invoke parse method
			}
			
			factors[i]=factor;
		}
		one.setFactors(factors);
	}
	@Override
	public void injectFactorOptions(Factor factor) {
		List<FactorOption> factorOptions = factorOptionDao.findByFactorId(factor.getId());
		
		if(factorOptions.size()>0){
			FactorOption[]arr=new FactorOption[factorOptions.size()];
			for(int i=0;i<factorOptions.size();i++){
				arr[i]=factorOptions.get(i);
			}
			factor.setFactorOptions(arr);
		}
				
	}
	@Override
	public void calculate(InsuranceForm form) throws Exception{
		if(form.getPremium()==null){
			form.setPremium(BigDecimal.ZERO);
		}
		for(SubInsuranceDetail subInsuranceDetail : form.getSubInsuranceDetails()){
			Insurance insurance = insuranceDao.findById(subInsuranceDetail.getInsuranceId());
			String formula="select "+insurance.getCalFormula()+"*1.0 from dual";
			BigDecimal premium=BigDecimal.ZERO;
			for(PolicyFactor policyFactor:subInsuranceDetail.getPolicyFactors()){
				String str=factorPremium(policyFactor,subInsuranceDetail,form);
				formula=formula.replace(policyFactor.getFactorName(), str);
			}
//			for(PolicyFactor policyFactor:subInsuranceDetail.getPolicyFactors()){
//				if(policyFactor.getFeeOrfacotr().equals("2")){
//					premium=premium.multiply(factorPremium(policyFactor,subInsuranceDetail,form));
//				}
//			}
			formula=formula.replace("?", "").replace("$", "");
			premium=runSQL(formula);
			subInsuranceDetail.setSubInsurancePremium(premium);
			form.setPremium(form.getPremium().add(premium));
		}
		
	}
	@PersistenceContext
	private EntityManager em;
	private BigDecimal runSQL(String formula) {
		Query query =  em.createNativeQuery(formula);
		Object singleResult = query.getSingleResult();
		return (BigDecimal) singleResult;
	}
	/**通过因子获取因子保费**/
	private String factorPremium(PolicyFactor policyFactor,SubInsuranceDetail subInsuranceDetail,InsuranceForm form)throws Exception {
		String premium=null;
		Factor factor=factorDao.findById(policyFactor.getFactorId());
		if(factor.getFactorDataType().equals("1")){
			premium=factor.getValue();
		}
		else if(factor.getFactorDataType().equals("2")){
			FactorOption factorOption = factorOptionDao.findById(policyFactor.getFactorOptionId());
			premium=factorOption.getValue();
		}else if (factor.getFactorDataType().equals("3")){
			premium=factorHandleService.handleFactor(policyFactor,subInsuranceDetail,form).setScale(4, BigDecimal.ROUND_HALF_UP).toString();
		}else if (factor.getFactorDataType().equals("4")){
			premium=policyFactor.getFactorOptionValue();
		}
		return premium;
	}
	@Override
	public void sortFactor(InsuranceForm form) {
		List<SubInsuranceDetail> subInsuranceDetails = form.getSubInsuranceDetails();
		PolicyFactor[] policyFactors = form.getPolicyFactors();
		for(SubInsuranceDetail one:subInsuranceDetails){
			for(PolicyFactor factor:policyFactors){
				if(one.getInsuranceId()==factor.getInsuranceId()){
					one.getPolicyFactors().add(factor);
				}
			}
		}
	}
	
	private ApplicationContext applicationContext;
	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		this.applicationContext=applicationContext;
	}
	
	
	
	public static void main(String[] args) throws Exception{
		String a="$a$";
		System.out.println(new BigDecimal(111.111).setScale(4, BigDecimal.ROUND_HALF_UP));
		
		
	}
	@Override
	public void saveForm(InsuranceForm form) {
		form.setStatus(0);
		InsuranceForm save = insuranceFormDao.save(form);
		for(SubInsuranceDetail subIns :form.getSubInsuranceDetails()){
			subIns.setInsuranceFormId(save.getId());
			SubInsuranceDetail save2 = subInsuranceDetailDao.save(subIns);
			for(PolicyFactor policyFactor:subIns.getPolicyFactors()){
				policyFactor.setInsuranceId(save2.getId());
				policyFactorDao.save(policyFactor);
			}
		}
	}
}





















